/**
 * 
 */
package net.kong.yumo.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.util.List;
import java.util.StringTokenizer;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.hasor.dataql.UdfSourceAssembly;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * <b>Title: </b>ToolUtil.java <br>
 * <b>Description: 工具类</b>
 * <b>Copyright: Copyright (c) 2006</b>
 * <b>Company:CES(FOSHAN)</b>
 * @author 植煜焕
 * @version 1.0 2011-11-20
 */

public class ToolUtil  implements UdfSourceAssembly {
	
	public ToolUtil() {
		
	}
	/**
	 * 日志对象
	 */
	public static Log logger = LogFactory.getLog(ToolUtil.class);
	/**
	 * 数组变字符串以逗号隔离
	 * @param list
	 * @return
	 */
	public static String listToString(List list) {
		
		return listToStringSpacer( list, ",");
	}
	/**
	 * 数组变字符串以传入的字符隔离
	 * @param list 
	 * @param spacer  间隔符
	 * @return
	 */
	public static String listToStringSpacer(List list,String spacer) {
		if(list == null || list.isEmpty()) {
			return "";
		}
		StringBuffer str=new StringBuffer();
		for(Object l:list) {
			str.append(l.toString());
			str.append(spacer);
		}
		str.delete(str.length()-spacer.length(), str.length());
		return str.toString();
	}
	/**
	 * 判断是否为空
	 * @param obj
	 * @return
	 */
	public static boolean isNull(Object obj){
		if((obj!=null)&&(!"".equals(obj)) )return false;
		else return true;
	}
	/**
	 * 判断是否为非空
	 * @param obj
	 * @return
	 */
	public static boolean isNotNull(Object obj){
		if((obj!=null)&&(!"".equals(obj.toString())))return true;
		else return false;
	}
	 /**
     * 判断对象是否为空，且对象的所有属性都为空
     * ps: boolean类型会有默认值false 判断结果不会为null 会影响判断结果
     *     序列化的默认值也会影响判断结果
     * @param object
     * @return
     */
    public  boolean objCheckIsNull(Object object){
        Class clazz = (Class)object.getClass(); // 得到类对象
        Field fields[] = clazz.getDeclaredFields(); // 得到所有属性
        boolean flag = true; //定义返回结果，默认为true
        for(Field field : fields){
            field.setAccessible(true);
            Object fieldValue = null;
            try {
                fieldValue = field.get(object); //得到属性值
                Type fieldType =field.getGenericType();//得到属性类型
                String fieldName = field.getName(); // 得到属性名
                System.out.println("属性类型："+fieldType+",属性名："+fieldName+",属性值："+fieldValue);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if(fieldValue != null){  //只要有一个属性值不为null 就返回false 表示对象不为null
                flag = false;
                break;
            }
        }
        return flag;
    }
	/**
	 * 判断是否为非空(忽略前导空白和尾部空白)
	 * @param obj
	 * @return
	 */
	public static boolean isTrimNotNull(Object obj){
		if((obj!=null)&&(!"".equals(obj.toString().trim())))return true;
		else return false;
	}
	
	/**
	 * 得到不为null得字符串
	 * @param obj
	 * @return
	 */
	public static String toNotNullString(Object obj){
		return obj==null?"":obj.toString();
	}
	
	  /** 将 null 转为空串 */
	  public static String nullToSpace(String str) {
	    if (str == null) {
	      return "";
	    } else {
	      return str;
	    }
	  }
	  
	  	/**
	  	 * 给字符串（可以是以逗号分开的字符串）加上单引号，
	  	 * @param strOld 字符串（可以是以逗号分开的字符串）
	  	 * @return  
	  	 */
		public static String addSingleQuotes(String strOld){
			if(ToolUtil.isNull(strOld)){
				return "";
			}
			String strNew="";
			StringTokenizer st=new StringTokenizer(strOld,",");
			while(st.hasMoreTokens()){
				String temp=st.nextToken();
				strNew+="'"+temp+"',";
			}
			strNew=strNew.substring(0,strNew.length()-1);
			return strNew;
		}
		
		

	  
	/**
	 * list的每一值为一个String数组，取得一个数组的第一个元素
	 * @param list
	 * @return
	 */
	public static String getData(List list){
		if((list==null)||(list.size()==0)){
			return "";
		}else{
			return ((String[])list.get(0))[0];
		}
	}
	
	/**
	 * list的每一值为一个String数组，取得索引位置为rowIndex的数组
	 * @param list
	 * @return
	 */
	public static String[] getData(List list,int rowIndex){
		if((list!=null)&&(list.size()>0)&&(list.size()>rowIndex)){
			return (String[])list.get(rowIndex);
		}
		else return null;
	}
	
	/**
	 * list的每一值为一个String数组，取得取得索引位置为rowIndex的数组的colIndex位置的元素
	 * @param list
	 * @return
	 */
	public static String getData(List list,int rowIndex,int colIndex){
		if((list!=null)&&(list.size()>0)&&(list.size()>rowIndex)){
			String[] row=(String[])list.get(rowIndex);
			if(row.length>colIndex)return row[colIndex];
			else return null;
		}
		else return null;
	}
	
	
	
   /**
    * 为二进制数组进行MD5加密
    * @param b
    * @return
    */
	public static String md5Encode(byte[] b) { 
	    String resultString = null;
	    try {
	    	MessageDigest md = MessageDigest.getInstance("MD5"); 
	    	resultString=byteArrayToHexString(md.digest(b)); 
	    }
	    catch (Exception ex) { 
	    	resultString = null;
	    } 
	    return resultString; 
	} 
	
	/**
	 * 为文件进行MD5加密，从而获取文件的MD5特征码
	 * @param fileName
	 * @return
	 */
	public static String md5Encode(String fileName) {
		return md5Encode(new File(fileName));
	} 
	
	
	/**
	 * 为文件进行MD5加密，从而获取文件的MD5特征码
	 * @param file
	 * @return
	 */
	public static String md5Encode(File file) {
		if (file.exists() && file.isFile()) {
			FileInputStream in = null;
			try {
				byte[] b = new byte[1024];
				MessageDigest md = MessageDigest.getInstance("MD5"); 
				in = new FileInputStream(file);
				while ((in.read(b)) != -1) {
					md.update(b);
				}
				return ToolUtil.byteArrayToHexString(md.digest());
			} catch (Exception e) {
				logger.error(e.toString());
				return "";
			} finally {
				try {
					in.close();
					in = null;
				} catch (Exception e) {
					logger.error(e.toString());
				}
			}
		}
		return "";
	} 
	
	private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5",
			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

	/** 
	 * 转换字节数组为16进制字串 
	 * @param b 字节数组 
	 * @return 16进制字串 
	 */
	public static String byteArrayToHexString(byte[] b) {
		StringBuffer resultSb = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			resultSb.append(byteToHexString(b[i]));
		}
		return resultSb.toString();
	}
	public static String byteToHexString(byte b) {
		int n = b;
		if (n < 0)
			n = 256 + n;
		int d1 = n / 16;
		int d2 = n % 16;
		return hexDigits[d1] + hexDigits[d2];
	}
	
	
	/**
	 * 将byte[]转化成16进制字符串
	 * 
	 * @param buf
	 * @return
	 */
	public static String byte2HexStr(byte buf[]) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < buf.length; i++) {
			String hex = Integer.toHexString(buf[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			sb.append(hex.toUpperCase());
		}
		return sb.toString();
	}

	/**
	 * 将16进制字符串转化成byte[]
	 * 
	 * @param buf
	 * @return
	 */
	public static byte[] hexStr2Byte(String hexStr) {
		if (hexStr.length() < 1)
			return null;
		byte[] result = new byte[hexStr.length() / 2];
		for (int i = 0; i < hexStr.length() / 2; i++) {

			int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
			int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
					16);
			result[i] = (byte) (high * 16 + low);
		}
		return result;
	}
	
	/**
	 * 将字符串数组组装成字符串 格式'xx','yy'
	 * @param strArray
	 * @return
	 */
	public static String getStringFromArray(String[] strArray){
		return getStringFromArray(strArray, "'", ",");
	}
	
	/**
	 * 
	 * @param strArray 字符串数组
	 * @param word     放在字符串前后的符号，如单引号
	 * @param op       字符串分隔符
	 * @return
	 */
	public static String getStringFromArray(String[] strArray, String word, String op){
		StringBuffer sb = new StringBuffer();
		if(strArray != null && strArray.length > 0){
			for(int i = 0; i < strArray.length; i++){
				if(i != 0){
					sb.append(op);
				}
				sb.append(word + strArray[i] + word);
			}
		}
		return sb.toString();
	}
	
	/**
	 * 将字符串转化成整形数（空或转化出错时返回0）
	 * @param strNumber
	 * @return 字符串对应的整形数（空或转化出错时返回0）
	 */
	public static int toInt(String strNumber){
		int iRet = 0;
		try{
			if(strNumber != null && strNumber.length() > 0){
				iRet = Integer.parseInt(strNumber);
			}
		}catch(Exception e){
			println(e.getMessage());
			iRet = 0;
		}
		return iRet;
	}
	
	/**
	 * 将字符型的数值自加1，非数值时返回1
	 * @param strVersion 
	 * @return
	 */
	public static String stringAddOne(String strVersion){
		return stringAdd(strVersion, 1);
	}
	
	/**
	 * 将字符型的数值自加step，非数值时返回step
	 * @param strVersion
	 * @param step
	 * @return
	 */
	public static String stringAdd(String strVersion, int step){
		return String.valueOf(toInt(strVersion) + step);
	}
	

	
	/**
	 * 用来输出调试信息，正式发布时可把函数体置空
	 * @param str
	 */
	public static void println(String str){
		System.out.println(str);
		
	}
	
	/**
	 * 根据整型数值转换成多少位不够位数前面加0的字符串
	 * @param value
	 * @param median
	 * @return
	 */
	public static String getIntToMedianString(int value, int median) {
		String result = "";
		String valueString = String.valueOf(value);
		int valueMedian = valueString.length();
		if(valueMedian < median) {
			for(int i = 0, c = median - valueMedian; i < c; i++) {
				result = result + "0";
			}
			result = result + valueString;
		} else {
			result = valueString;
		}
		return result;
	}
	
	/**
	 * 将字符转成UTF-8，解决GET方式传递中文时出现的乱码问题
	 * 在页面中，必须对中文值用javascript的encodeURI进行转化
	 * @param str
	 * @return
	 */
	public static String changeToUTF8(String str){
		
		return 	changeCharEncoding(str,"UTF-8");
	}

	/**
	 * 将字符转成GBK，解决GET方式传递中文时出现的乱码问题
	 * 在页面中，必须对中文值用javascript的encodeURI进行转化
	 * @param str
	 * @return
	 */
	public static String changeToGBK(String str){
		return 	changeCharEncoding(str,"GBK");	
	}
	
	/**
	 * 将字符转成encoding（字符集），解决GET方式传递中文时出现的乱码问题
	 * 在页面中，必须对中文值用javascript的encodeURI进行转化
	 * @param str
	 * @param encoding
	 * @return
	 */
	public static String changeCharEncoding(String str,String encoding){
		
		try {
			return  new String(str.getBytes("ISO-8859-1"),encoding);
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return null;
		}	
	}
	
	
	
	
	
	/**
	 * 对字符串进行BAS464加密
	 * @param str
	 * @return
	 */
	public static String base64encoder(String enstr){
		BASE64Encoder encoder = new BASE64Encoder();
		return encoder.encode(enstr.getBytes());
	}
	
	
	/**
	 * 对字符串根据私钥，进行base64加密
	 * @param enstr
	 * @param mykey
	 * @return
	 */
	public static String  base64encode(String enstr,String mykey){
		String md5MykeyStr=md5Encode(mykey.getBytes());
		String base64MykeyStr=base64encoder(md5MykeyStr.substring(16, 26)).replaceAll("=", "");
		String base64Enstr=base64encoder(enstr);
		
		int len=base64Enstr.length();
		
		//获取随机数
		int random=(int)(Math.random()*len);
		int random2=(int)(Math.random()*5);
		enstr= base64Enstr.substring(0, random)+"/"+ base64MykeyStr +base64Enstr.substring(random);
		if(random2==2) enstr= base64Enstr.substring(0, random)+ base64MykeyStr+"/" +base64Enstr.substring(random);
		if(random2==3) enstr= base64Enstr.substring(0, random)+"+"+ base64MykeyStr +base64Enstr.substring(random);
		if(random2==4) enstr= base64Enstr.substring(0, random)+ base64MykeyStr+"+" +base64Enstr.substring(random);
	    return enstr;
	}
	
	/**
	 * 对字符串进行base64解密，如果解密失败，返回NULL
	 * @param destr
	 * @return
	 */
	public static String  base64decode(String destr){
		BASE64Decoder decoder =new BASE64Decoder();
		try {
			return new String((decoder.decodeBuffer(destr)));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			return null;
		}
	}
	/**
	 * 对字符串进行base64解密，如果解密失败，返回NULL
	 * @param destr
	 * @param mykey
	 * @return
	 */
	public static String  base64decode(String destr,String mykey){
	
		String md5MykeyStr=md5Encode(mykey.getBytes());
		String base64MykeyStr=base64encoder(md5MykeyStr.substring(16, 26)).replaceAll("=", "");;
		destr=destr.replace("/"+base64MykeyStr, "");
		destr=destr.replace("+"+base64MykeyStr, "");
		destr=destr.replace(base64MykeyStr+"/", "");
		destr=destr.replace(base64MykeyStr+"+", "");
        return base64decode(destr);

	}
	
	public static boolean isAllNumber(String str){
		if(str!=""){
			for (int i=0; i<str.length(); i++) { 
				char c = str.charAt(i); 
				if (c<'0' || '9'<c) { 
					return false; 
				} 
			}
			return true;
		}else{
			return false;
		}
	}
	/**
	 *  根据输入的字段名获取对应的英文名
	 * @param obj
	 * @param fieldName
	 * @return
	 */
    public static String getProperName(Object obj,String fieldName){
    	String field=fieldName;
    	Field[] fields = obj.getClass().getDeclaredFields();
    	for (Field f : fields) {
			String name = f.getName();
			String firstLetter = name.substring(0, 1).toUpperCase();
			String getMethodName = "get" + firstLetter + name.substring(1);
			Method m;
			try {
				m = obj.getClass().getMethod(getMethodName);
				if (m.isAnnotationPresent((Class<? extends Annotation>) PropertyMeta.class)) {
					PropertyMeta meta = m.getAnnotation(PropertyMeta.class);
					if(isEnglish(fieldName)){
						if(fieldName.equals(name)){
							field=name;
							break;
						}
					}else{
						if(meta.name().equals(fieldName)){
							field=name;
							break;
						}
					}
				}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
		}
    	return field;
    }
    /**
     * 判断字符是否是英文
     * @param charaString
     * @return
     */
    public static boolean isEnglish(String charaString) {
    	return charaString.matches("^[a-zA-Z]*");
    }
    
    /**
     * AES加密
     * @param str
     * @return
     */
    public static String EncrypAES(String str){
		EncrypAES en=EncrypAES.getInstance();
		en.initKey();
		String tmp="";
		if(null!=en){
			try {
				tmp=ToolUtil.byte2HexStr(en.Encrytor(str));
				return tmp;
			} catch (InvalidKeyException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IllegalBlockSizeException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (BadPaddingException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
		return null;
    }
    
}


